/*
 * CC3OpenGLES11Materials.m
 *
 * cocos3d 0.6.1
 * Author: Bill Hollings
 * Copyright (c) 2010-2011 The Brenwill Workshop Ltd. All rights reserved.
 * http://www.brenwill.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * http://en.wikipedia.org/wiki/MIT_License
 * 
 * See header file CC3OpenGLES11Materials.h for full API documentation.
 */

#include "CC3OpenGLES11Materials.h"


#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerMaterialColor

//@implementation CC3OpenGLES11StateTrackerMaterialColor
//
//-(void) getGLValue {
//	glGetMaterialfv(GL_FRONT, name, (GLfloat*)&originalValue);
//}
//
//-(void) setGLValue {
//	glMaterialfv(GL_FRONT_AND_BACK, name, (GLfloat*)&value);
//}
//
//@end

CC3OpenGLES11StateTrackerMaterialColor::CC3OpenGLES11StateTrackerMaterialColor()
{
}

CC3OpenGLES11StateTrackerMaterialColor::~CC3OpenGLES11StateTrackerMaterialColor()
{
}

CC3OpenGLES11StateTrackerMaterialColor* CC3OpenGLES11StateTrackerMaterialColor::trackerForState(GLenum aName)
{
	CC3OpenGLES11StateTrackerMaterialColor* pState = new CC3OpenGLES11StateTrackerMaterialColor;
	if (pState) 
	{
		pState->autorelease();
		pState->initForState(aName, NULL);
		return pState;
	}
	
	return NULL;
}

void CC3OpenGLES11StateTrackerMaterialColor::getGLValue()
{
	glGetMaterialfv(GL_FRONT, name, (GLfloat*)&originalValue);
}

void CC3OpenGLES11StateTrackerMaterialColor::setGLValue()
{
	glMaterialfv(GL_FRONT_AND_BACK, name, (GLfloat*)&value);
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerMaterialFloat

//@implementation CC3OpenGLES11StateTrackerMaterialFloat
//
//-(void) getGLValue {
//	glGetMaterialfv(GL_FRONT, name, (GLfloat*)&originalValue);
//}
//
//-(void) setGLValue {
//	glMaterialf(GL_FRONT_AND_BACK, name, value);
//}
//
//@end

CC3OpenGLES11StateTrackerMaterialFloat::CC3OpenGLES11StateTrackerMaterialFloat()
{
}

CC3OpenGLES11StateTrackerMaterialFloat::~CC3OpenGLES11StateTrackerMaterialFloat()
{
}

CC3OpenGLES11StateTrackerMaterialFloat* CC3OpenGLES11StateTrackerMaterialFloat::trackerForState(GLenum aName)
{
	CC3OpenGLES11StateTrackerMaterialFloat* pState = new CC3OpenGLES11StateTrackerMaterialFloat;
	if (pState) 
	{
		pState->autorelease();
		pState->initForState(aName, NULL);
		return pState;
	}
	
	return NULL;
}

void CC3OpenGLES11StateTrackerMaterialFloat::getGLValue()
{
	glGetMaterialfv(GL_FRONT, name, (GLfloat*)&originalValue);
}

void CC3OpenGLES11StateTrackerMaterialFloat::setGLValue()
{
	glMaterialf(GL_FRONT_AND_BACK, name, value);
}


#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerMaterialBlend

//@implementation CC3OpenGLES11StateTrackerMaterialBlend
//
//@synthesize sourceBlend, destinationBlend;
//
//-(void) dealloc {
//	[sourceBlend release];
//	[destinationBlend release];
//	[super dealloc];
//}
//
//-(void) initializeTrackers {
//	self.sourceBlend = [CC3OpenGLES11StateTrackerEnumeration trackerForState: GL_BLEND_SRC];
//	self.destinationBlend = [CC3OpenGLES11StateTrackerEnumeration trackerForState: GL_BLEND_DST];
//}
//
//+(CC3GLESStateOriginalValueHandling) defaultOriginalValueHandling {
//	return kCC3GLESStateOriginalValueReadOnceAndRestore;
//}
//
//-(void) setOriginalValueHandling: (CC3GLESStateOriginalValueHandling) origValueHandling {
//	sourceBlend.originalValueHandling = origValueHandling;
//	destinationBlend.originalValueHandling = origValueHandling;
//	[super setOriginalValueHandling: origValueHandling];
//} 
//
//-(BOOL) valueIsKnown {
//	return sourceBlend.valueIsKnown && destinationBlend.valueIsKnown;
//}
//
//-(void) setValueIsKnown:(BOOL) aBoolean {
//	sourceBlend.valueIsKnown = aBoolean;
//	destinationBlend.valueIsKnown = aBoolean;
//}
//
//-(void) open {
//	[sourceBlend open];
//	[destinationBlend open];
//}
//
//-(void) restoreOriginalValue {
//	[self applySource: sourceBlend.originalValue
//	   andDestination: destinationBlend.originalValue];
//}
//
//-(void) applySource: (GLenum) srcBlend andDestination: (GLenum) dstBlend {
//	BOOL shouldSetGL = self.shouldAlwaysSetGL;
//	shouldSetGL |= [sourceBlend attemptSetValue: srcBlend];
//	shouldSetGL |= [destinationBlend attemptSetValue: dstBlend];
//	if (shouldSetGL) {
//		glBlendFunc(sourceBlend.value, destinationBlend.value);
//	}
//	LogTrace("%@ %@ %@ = %@ and %@ = %@", [self class], (shouldSetGL ? @"applied" : @"reused"),
//			 NSStringFromGLEnum(sourceBlend.name), NSStringFromGLEnum(sourceBlend.value),
//			 NSStringFromGLEnum(destinationBlend.name), NSStringFromGLEnum(destinationBlend.value));
//}
//
//-(NSString*) description {
//	return [NSString stringWithFormat: @"%@:\n    %@\n    %@",
//			[self class], sourceBlend, destinationBlend];
//}
//
//@end

CC3OpenGLES11StateTrackerMaterialBlend::CC3OpenGLES11StateTrackerMaterialBlend() :
	sourceBlend(NULL),
	destinationBlend(NULL)
{
}

CC3OpenGLES11StateTrackerMaterialBlend::~CC3OpenGLES11StateTrackerMaterialBlend()
{
	sourceBlend->release();
	destinationBlend->release();
}

CC3OpenGLES11StateTrackerMaterialBlend* CC3OpenGLES11StateTrackerMaterialBlend::tracker()
{
	CC3OpenGLES11StateTrackerMaterialBlend* pState = new CC3OpenGLES11StateTrackerMaterialBlend;
	if (pState) 
	{
		pState->initializeTrackers();
		pState->autorelease();
	}
	
	return pState;
}

void CC3OpenGLES11StateTrackerMaterialBlend::applySource(GLenum srcBlend, GLenum dstBlend)
{
	bool shouldSetGL = shouldAlwaysSetGL;
	shouldSetGL |= sourceBlend->attemptSetValue(srcBlend);
	shouldSetGL |= destinationBlend->attemptSetValue(dstBlend);
	if (shouldSetGL) 
	{
		glBlendFunc(sourceBlend->getValue(), destinationBlend->getValue());
	}
	//LogTrace("%@ %@ %@ = %@ and %@ = %@", [self class], (shouldSetGL ? @"applied" : @"reused"),
//			 NSStringFromGLEnum(sourceBlend.name), NSStringFromGLEnum(sourceBlend.value),
//			 NSStringFromGLEnum(destinationBlend.name), NSStringFromGLEnum(destinationBlend.value));
}

void CC3OpenGLES11StateTrackerMaterialBlend::initializeTrackers()
{
	setSourceBlend(CC3OpenGLES11StateTrackerEnumeration::trackerForState(GL_BLEND_SRC));
	
	setDestinationBlend(CC3OpenGLES11StateTrackerEnumeration::trackerForState(GL_BLEND_DST));
}

CC3GLESStateOriginalValueHandling CC3OpenGLES11StateTrackerMaterialBlend::defaultOriginalValueHandling()
{
	return kCC3GLESStateOriginalValueReadOnceAndRestore;
}

void CC3OpenGLES11StateTrackerMaterialBlend::setOriginalValueHandling(CC3GLESStateOriginalValueHandling origValueHandling)
{
	sourceBlend->setOriginalValueHandling(origValueHandling);
	destinationBlend->setOriginalValueHandling(origValueHandling);
	CC3OpenGLES11StateTrackerComposite::setOriginalValueHandling(origValueHandling);
}

bool CC3OpenGLES11StateTrackerMaterialBlend::valueIsKnown()
{
	return sourceBlend->getValueIsKnown() && destinationBlend->getValueIsKnown();
}

void CC3OpenGLES11StateTrackerMaterialBlend::setValueIsKnown(bool aBoolean)
{
	sourceBlend->setValueIsKnown(aBoolean);
	destinationBlend->setValueIsKnown(aBoolean);
}

void CC3OpenGLES11StateTrackerMaterialBlend::open()
{
	if (sourceBlend) 
	{
		sourceBlend->open();
	}
	
	if (destinationBlend) 
	{
		destinationBlend->open();
	}
}

void CC3OpenGLES11StateTrackerMaterialBlend::restoreOriginalValue()
{
	applySource(sourceBlend->getOriginalValue(), destinationBlend->getOriginalValue());
}


#pragma mark -
#pragma mark CC3OpenGLES11Materials

//@implementation CC3OpenGLES11Materials
//
//@synthesize ambientColor;
//@synthesize diffuseColor;
//@synthesize specularColor;
//@synthesize emissionColor;
//@synthesize shininess;
//@synthesize blend;
//
//-(void) dealloc {
//	[ambientColor release];
//	[diffuseColor release];
//	[specularColor release];
//	[emissionColor release];
//	[shininess release];
//	[blend release];
//	[super dealloc];
//}
//
//-(void) initializeTrackers {
//	self.ambientColor = [CC3OpenGLES11StateTrackerMaterialColor trackerForState: GL_AMBIENT];
//	self.diffuseColor = [CC3OpenGLES11StateTrackerMaterialColor trackerForState: GL_DIFFUSE];
//	self.specularColor = [CC3OpenGLES11StateTrackerMaterialColor trackerForState: GL_SPECULAR];
//	self.emissionColor = [CC3OpenGLES11StateTrackerMaterialColor trackerForState: GL_EMISSION];
//	self.shininess = [CC3OpenGLES11StateTrackerMaterialFloat trackerForState: GL_SHININESS];
//	self.blend = [CC3OpenGLES11StateTrackerMaterialBlend tracker];
//}
//
//-(void) open {
//	LogTrace("Opening %@", [self class]);
//	[ambientColor open];
//	[diffuseColor open];
//	[specularColor open];
//	[emissionColor open];
//	[shininess open];
//	[blend open];
//}
//
//-(void) close {
//	LogTrace("Closing %@", [self class]);
//	[ambientColor close];
//	[diffuseColor close];
//	[specularColor close];
//	[emissionColor close];
//	[shininess close];
//	[blend close];
//}
//
//-(NSString*) description {
//	NSMutableString* desc = [NSMutableString stringWithCapacity: 500];
//	[desc appendFormat: @"%@:", [self class]];
//	[desc appendFormat: @"\n    %@ ", ambientColor];
//	[desc appendFormat: @"\n    %@ ", diffuseColor];
//	[desc appendFormat: @"\n    %@ ", specularColor];
//	[desc appendFormat: @"\n    %@ ", emissionColor];
//	[desc appendFormat: @"\n    %@ ", shininess];
//	[desc appendFormat: @"\n    %@ ", blend];
//	return desc;
//}
//
//@end

CC3OpenGLES11Materials::CC3OpenGLES11Materials() :
	ambientColor(NULL),
	diffuseColor(NULL),
	specularColor(NULL),
	emissionColor(NULL),
	shininess(NULL),
	blend(NULL)
{
	
}

CC3OpenGLES11Materials::~CC3OpenGLES11Materials()
{
	ambientColor->release();
	diffuseColor->release();
	specularColor->release();
	emissionColor->release();
	shininess->release();
	blend->release();
}

CC3OpenGLES11Materials* CC3OpenGLES11Materials::tracker()
{
	CC3OpenGLES11Materials* pState = new CC3OpenGLES11Materials;
	if (pState) 
	{
		pState->initializeTrackers();
		pState->autorelease();
	}
	
	return pState;
}

void CC3OpenGLES11Materials::open()
{
	//LogTrace("Opening %@", [self class]);
	ambientColor->open();
	diffuseColor->open();
	specularColor->open();
	emissionColor->open();
	shininess->open();
	blend->open();
}

void CC3OpenGLES11Materials::close()
{
	//LogTrace("Closing %@", [self class]);
	ambientColor->close();
	diffuseColor->close();
	specularColor->close();
	emissionColor->close();
	shininess->close();
	blend->close();
}

void CC3OpenGLES11Materials::initializeTrackers()
{
	setAmbientColor(CC3OpenGLES11StateTrackerMaterialColor::trackerForState(GL_AMBIENT));
	setDiffuseColor(CC3OpenGLES11StateTrackerMaterialColor::trackerForState(GL_DIFFUSE));
	setSpecularColor(CC3OpenGLES11StateTrackerMaterialColor::trackerForState(GL_SPECULAR));
	setEmissionColor(CC3OpenGLES11StateTrackerMaterialColor::trackerForState(GL_EMISSION));
	setShininess(CC3OpenGLES11StateTrackerMaterialFloat::trackerForState(GL_SHININESS));
	setBlend(CC3OpenGLES11StateTrackerMaterialBlend::tracker());
}

